<template>
  <view w-full box-border pa-20rpx>
    <view w-full bg-white rounded-20rpx box-border px-20rpx pb-30rpx mb-20rpx>
      <view w-full h-90rpx flex items-center style="border-bottom: 1px solid #eeeeee">题库一</view>
      <view h-100rpx flex justify-between items-center>
        <view text-24rpx flex items-end>
          答题进度
          <text ml-16rpx text-36rpx line-height-none>{{ userAnswerNum }}</text>
          /{{ questionNum }}题
        </view>
        <view v-if="answerEndTime" text-28rpx flex items-center>
          <image w-40rpx h-40rpx mr-10rpx src="/pages/exam/static/time.png"></image>
          <!-- <nut-countdown :endTime="end" format="DD天HH时mm分ss秒" /> -->
          <xm-count-down :expireTime="answerEndTime" @end="goBack" preTxt="" color="#000"></xm-count-down>
        </view>
      </view>
      <view w-360rpx h-20rpx rounded-10rpx bg="#EEEEEE">
        <view bg="#FCC300" h-20rpx rounded-10rpx :style="{ width: (userAnswerNum / questionNum) * 360 + 'rpx' }"></view>
      </view>
    </view>
    <view w-full h-60rpx flex items-center justify-center mb-20rpx>
      <view
        h-60rpx
        w-120rpx
        rounded-l-30rpx
        flex
        items-center
        justify-center
        style="border: 1px solid #fcc300"
        :style="{ backgroundColor: answerModel == 1 ? '#FCC300' : '#fff' }"
        @click="answerModel = 1">
        答题
      </view>
      <view
        h-60rpx
        w-120rpx
        rounded-r-30rpx
        flex
        items-center
        justify-center
        style="border: 1px solid #fcc300"
        :style="{ backgroundColor: answerModel == 2 ? '#FCC300' : '#fff' }"
        @click="answerModel = 2">
        背题
      </view>
    </view>
    <!-- <view w-full :style="{ height: questionHeight + 'px' }" style="border: 1px solid red"></view> -->
    <xm-swiper
      ref="swiperRef"
      v-model="curQuestionIndex"
      :items="questions"
      :height="questionHeight"
      :style="{ height: questionHeight + 'px' }">
      <template #default="{ item: question }">
        <scroll-view
          v-if="isShowQuestion"
          scroll-y
          enhanced
          :show-scrollbar="false"
          :style="{ height: questionHeight + 'px' }"
          bg-white
          rounded-20rpx
          px-20rpx
          py-30rpx
          box-border>
          <xm-question
            v-model="question.userAnswers"
            :type="question.type"
            :markType="question.markType"
            :title="question.title"
            :score="question.score"
            :answers="question.answers"
            :userScore="question.userScore"
            :options="question.options"
            :analysis="question.analysis"
            :editable="exering(question)"
            :analysisShow="analysisShow(question)"
            :answerShow="answerShow(question)"
            @change="(userAnswers: string[]) => autoNext(question, userAnswers)">
            <template #title-pre>
              <text>{{ question?.no }}、【{{ typeDict[question.type] }}】</text>
            </template>
            <template #title-post>
              <text>（{{ question?.score }}分）</text>
            </template>
          </xm-question>
        </scroll-view>
      </template>
    </xm-swiper>
  </view>
  <view bg-white rounded-20rpx ml-20rpx w-710rpx h-120rpx flex justify-between items-center position-fixed bottom-46rpx>
    <image w-40rpx h-40rpx ml-40rpx src="/pages/exam/static/datika.png" @click="answerSheet.open()"></image>
    <view flex justify-end items-center text-28rpx>
      <view
        v-if="curQuestionIndex != 0"
        w-220rpx
        h-80rpx
        bg="#FCC300"
        rounded-40rpx
        flex
        justify-center
        items-center
        mr-28rpx
        @click="pre">
        上一题
      </view>
      <view
        v-if="curQuestionIndex != questionNum - 1"
        w-220rpx
        h-80rpx
        bg="#FCC300"
        rounded-40rpx
        flex
        justify-center
        items-center
        @click="next">
        下一题
      </view>
      <view w-126rpx h-80rpx flex justify-center items-center @click="finish">完成</view>
    </view>
  </view>
  <view class="mypaper-foot">
    <xm-popup ref="answerSheet" name="答题卡" class="answer-sheet">
      <view class="answer-sheet-head">
        <!-- <view class="answer-sheet-head__state answer-sheet-head__state--mark"></view>
        <text class="answer-sheet-head__name">标记</text> -->
        <view class="answer-sheet-head__state answer-sheet-head__state--answer"></view>
        <text class="answer-sheet-head__name">已答</text>

        <view class="answer-sheet-head__state answer-sheet-head__state--true"></view>
        <text class="answer-sheet-head__name">答对</text>
        <view class="answer-sheet-head__state answer-sheet-head__state--false"></view>
        <text class="answer-sheet-head__name">答错</text>
        <view class="answer-sheet-head__state answer-sheet-head__state--half"></view>
        <text class="answer-sheet-head__name">半对</text>
      </view>
      <view class="answer-sheet-main">
        <template v-for="(question, index) in questions" :index="index" :key="index">
          <view
            @click="curQuestionIndex = index"
            :class="[
              'answer-sheet__question-no',
              { 'answer-sheet__question-no--answer': isAnswer(question) },
              { 'answer-sheet__question-no--half': isHalf(question) },
              { 'answer-sheet__question-no--true': isTrue(question) },
              { 'answer-sheet__question-no--false': isFalse(question) },
              { 'answer-sheet__question-no--mark': isMark(question) } // 标记最大，放到最后覆盖
            ]">
            <text>{{ question.no }}</text>
          </view>
        </template>
      </view>
    </xm-popup>
  </view>
</template>

<script setup lang="ts">
import { onLoad, onShow } from '@dcloudio/uni-app'
import { selectTopicQuestion, selectExmQuestion, addExmQuestionTypeCount } from '@/api/examStudy'
import { addErrorQuestion } from '@/api/examRecord'
import xmSwiper from '@/pages/exam/components/xm-swiper/xm-swiper.vue'
import xmQuestion from '@/pages/exam/components/xm-question/xm-question.vue'
import xmPopup from '@/pages/exam/components/xm-popup/xm-popup.vue'
import xmCountDown from '@/pages/exam/components/xm-count-down/xm-count-down.vue'
import type { Question } from '@/ts/question.d.ts'
const answerSheet = ref() // 答题卡
const marks = ref<number[]>([]) // 标记

const answerEndTime = ref<any>('')
const questions = ref<Question[]>([{} as Question]) // 试题列表
const answerModel = ref(1) // 答题模式（1：答题；2：背题）
const curQuestionIndex = ref<number>(0) // 当前试题索引
const id = ref<string | number>('')
const type = ref<number>(1) // 1专题;2其他
const isShowQuestion = ref(true)
const swiperRef = ref()

//试题类型（1：单选；2：多选；3：填空；4：判断；5：问答）
const typeDict = ref<any>({
  1: '单选',
  2: '多选',
  3: '填空',
  4: '判断',
  5: '问答'
})

const exering = computed(() => (question: Question) => answerModel.value === 1 && question.userScore == null) // 练习中
const analysisShow = computed(() => (question: Question) => answerModel.value === 2 || question.userScore != null) // 解析显示
const answerShow = computed(() => (question: Question) => answerModel.value === 2) // 标准答案显示
const questionNum = computed(() => questions.value.length) // 试题数量
const userAnswerNum = computed(() =>
  questions.value.reduce(
    (total, question) =>
      (question?.userAnswers?.some((userAnswer) => userAnswer.length) ?? false) ? total + 1 : total,
    0
  )
) // 用户答题数量

const isAnswer = computed(() => (question: Question) => question.userAnswers?.some((userAnswer) => userAnswer.length)) // 是否答题
const isMark = computed(() => (question: Question) => marks.value.includes(question.no)) // 是否标记
const isHalf = computed(
  () => (question: Question) =>
    question.userScore != null && question.userScore > 0 && question.userScore !== question.score
) // 是否半对
const isTrue = computed(
  () => (question: Question) => question.userScore != null && question.userScore === question.score
) // 是否答对
const isFalse = computed(() => (question: Question) => question.userScore != null && question.userScore === 0) // 是否答错

// 试题滚动高度
const questionHeight = computed(() => {
  const systemInfo: any = uni.getSystemInfoSync()
  return systemInfo.windowHeight - (systemInfo.screenWidth / 750) * 548
})

// 上一题
async function pre() {
  // 如果是答题模式，并且是单选多选判断，并且已答题，并且没打分
  let curQuestion = questions.value[curQuestionIndex.value]
  if (
    answerModel.value === 1 &&
    (curQuestion.type === 1 || curQuestion.type === 2 || curQuestion.type === 4) &&
    answered(curQuestion) &&
    !scored(curQuestion)
  ) {
    // 智能打分
    await scoring(curQuestion)
    // 如果不是满分，不进入下一题（第二次就打分了，不在进入）
    if (curQuestion.score != curQuestion.userScore) {
      return
    }
  }

  curQuestionIndex.value <= 0 ? (curQuestionIndex.value = questionNum.value - 1) : curQuestionIndex.value-- // 划到上一题
  // swiperRef.value.pre()
  isShowQuestion.value = false
  setTimeout(() => {
    isShowQuestion.value = true
  }, 10)
}

// 下一题
async function next() {
  let curQuestion = questions.value[curQuestionIndex.value]
  // 如果是单选多选判断，并且已答题，并且没打分
  if (
    (curQuestion.type === 1 || curQuestion.type === 2 || curQuestion.type === 3 || curQuestion.type === 4) &&
    answered(curQuestion) &&
    !scored(curQuestion)
  ) {
    // 智能打分
    await scoring(curQuestion)
    // 如果不是满分，不进入下一题（第二次就打分了，不在进入）
    if (curQuestion.score != curQuestion.userScore) {
      addErrQuestion(curQuestion)
      return
    }
  }
  curQuestionIndex.value >= questionNum.value - 1 ? (curQuestionIndex.value = 0) : curQuestionIndex.value++

  isShowQuestion.value = false
  setTimeout(() => {
    isShowQuestion.value = true
  }, 10)
}

// 自动下一题
function autoNext(question: Question, userAnswers: string[]) {
  // 如果是单选或判断，并且是答题模式
  if ((question.type === 1 || question.type === 4) && answerModel.value === 1) {
    // 智能打分
    scoring(question)
    // 并且答对，自动下一题
    if (question.score === question.userScore) {
      setTimeout(() => {
        next()
      }, 500)
    } else {
      addErrQuestion(question)
    }
  }
}

// 完成
async function finish() {
  let unAnswerNum = questionNum.value - userAnswerNum.value
  uni.showModal({
    title: '提示消息',
    content: unAnswerNum ? `剩余${unAnswerNum}道题未答，是否退出？` : `共${questionNum.value}道题全部已答，是否退出？`,
    showCancel: true,
    success: async (res) => {
      if (res.cancel) {
        return
      }

      // uni.reLaunch({ url: '/pages/exam/index' })
      uni.navigateBack({
        delta: type.value == 1 ? 1 : 2
      })
    }
  })
}

// 有答案
function answered(question: Question) {
  return (question.userAnswers || []).some((userAnswer: any) => userAnswer.length)
}

// 打分
function scoring(question: Question): Promise<void> {
  // question.userScore = question.score
  // return Promise.resolve()
  return new Promise((resolve, reject) => {
    try {
      if (answerModel.value === 2) {
        return resolve()
      }

      // 如果是单选或判断，并且没打分，并且有答案
      if ((question.type === 1 || question.type === 4) && !scored(question) && answered(question)) {
        // 智能打分
        question.userScore = 0
        if (question.userAnswers?.[0] === question.answers?.[0]) {
          question.userScore = question.score
        }
        return resolve()
      }

      // 如果是多选，并且没打分，并且有答案
      if (question.type === 2 && !scored(question) && answered(question)) {
        // 智能打分
        question.userScore = 0
        const { userAnswers = [], answers = [] } = question
        const include = userAnswers.every((userAnswer: string) => answers.includes(userAnswer))
        if (question.answers?.length === question.userAnswers?.length && include) {
          question.userScore = question.score // 全对满分
        } else if (include) {
          question.userScore = question.scores[0] // 半对指定分
        }
        return resolve()
      }

      // 填空题
      if (question.type === 3 && !scored(question) && answered(question)) {
        // 智能打分
        question.userScore = 0
        const { userAnswers = [], answers = [] } = question
        const include = userAnswers.every((userAnswer: string) => answers.includes(userAnswer))
        if (question.answers?.length === question.userAnswers?.length && include) {
          question.userScore = question.score // 全对满分
        } else if (include) {
          question.userScore = question.scores[0] // 半对指定分
        }
        return resolve()
      }

      resolve() // 如果没有任何匹配条件，直接 resolve
    } catch (error) {
      reject(error) // 捕获异常并拒绝 Promise
    }
  })
}

// 已打分
function scored(question: Question) {
  return question.userScore != null
}

function addErrQuestion(question: Question) {
  addErrorQuestion({ questionId: question.id, answers: question.userAnswers })
}

// 试题查询
async function questionQuery() {
  // let { data } = await myExerQuestionList2({ exerId: myExer.id });
  const api = type.value === 1 ? selectTopicQuestion : selectExmQuestion
  const response = await api({ [type.value === 1 ? 'exerId' : 'questionTypeId']: id.value } as any)
  questions.value = (response.data.result as any[]).map((question: Question, index) => {
    question.no = index + 1
    question.userAnswers = [] // 接口没有，填充
    question.userScore = question.userScore ?? null // 接口没有，填充
    return question
  })
}

function goBack() {
  uni.showModal({
    title: '提示消息',
    content: '练习截止时间到',
    confirmText: '返回',
    cancelText: '返回首页',
    success: function (res) {
      if (res.confirm) {
        uni.navigateBack()
      } else if (res.cancel) {
        uni.navigateTo({ url: `/pages/index` })
      }
    }
  })
}

onMounted(() => {})
onLoad((options: any) => {
  id.value = options.id
  if (options.type) {
    type.value = parseInt(options.type)
  }
  if (type.value === 1) {
    answerEndTime.value = options.endTime
  }

  questionQuery()
  addExmQuestionTypeCount()
})
</script>
<style>
page {
}
</style>
<style scoped lang="scss">
// #ifdef MP-WEIXIN
:deep(swiper) {
  height: 100%;
  swiper-item {
    & > view {
      height: 100%;
    }
  }
}
// #endif
.mypaper-foot {
  display: flex;
  margin: 20rpx 30rpx;
  .answer-nav {
    flex: 1;
    display: flex;
    align-items: center;
    .answer-nav__icon {
      background-clip: text;
      color: transparent;
      background-image: linear-gradient(0deg, #259ff8, #04c7f2);
    }
    .answer-nav__outer {
      display: flex;
      flex-direction: column;
      margin-left: 10rpx;
      .answer-nav__inner {
        display: flex;
        justify-content: center;
        line-height: 20rpx;
        .answer-nav__cur {
          font-size: 24rpx;
          color: #0d9df6;
        }
        .answer-nav__total {
          font-size: 24rpx;
          color: #303133;
        }
      }
      .answer-nav__text {
        font-size: 24rpx;
        color: #8f939c;
      }
    }
  }
  .mypaper-foot__pre-question {
    width: 160rpx;
    height: 66rpx;
    line-height: 66rpx;
    font-size: 30rpx;
    color: #0d9df6;
    border-radius: 33rpx;
    margin: 0rpx 0rpx 0rpx 20rpx;
    background-color: white;
    border: 1rpx solid #04c7f2;
    &::after {
      border: 0rpx;
    }
  }
  .mypaper-foot__next-question {
    width: 160rpx;
    height: 66rpx;
    line-height: 66rpx;
    font-size: 30rpx;
    color: #0d9df6;
    border-radius: 33rpx;
    margin: 0rpx 0rpx 0rpx 20rpx;
    background-color: white;
    border: 1rpx solid #04c7f2;
    &::after {
      border: 0rpx;
    }
  }
  .mypaper-foot__finish {
    width: 160rpx;
    height: 66rpx;
    line-height: 66rpx;
    font-size: 32rpx;
    color: #ffffff;
    border-radius: 33rpx;
    background: linear-gradient(to right, #04c7f2 0%, #259ff8 100%);
    margin: 0rpx 0rpx 0rpx 20rpx;
    &::after {
      border: 0rpx;
    }
  }
  .answer-sheet {
    .answer-sheet-head {
      display: flex;
      justify-content: end;
      align-items: center;
      margin-bottom: 30rpx;
      .answer-sheet-head__state {
        width: 22rpx;
        height: 22rpx;
        margin-left: 30rpx;
        border-radius: 50%;
        background: #000;
        border: 1rpx solid #000;
        background: #e9e9eb;
        border: 1rpx solid #8f939c;
      }
      .answer-sheet-head__state--answer {
        background: #d4e4ff;
        border: 1rpx solid #2979ff;
      }
      .answer-sheet-head__state--mark {
        background: #fdedd9;
        border: 1rpx solid #f3a73f;
      }
      .answer-sheet-head__state--true {
        background: #d1f2d7;
        border: 1rpx solid #18bc37;
      }
      .answer-sheet-head__state--false {
        background: #fad8d6;
        border: 1rpx solid #e43d33;
      }
      .answer-sheet-head__state--half {
        background: linear-gradient(to bottom, #fad8d6 50%, #d1f2d7 50%);
        border: 1rpx solid #18bc37;
      }
      .answer-sheet-head__name {
        margin-left: 10rpx;
        font-size: 30rpx;
        color: #8f939c;
      }
    }
    .answer-sheet-main {
      flex: 1;
      display: grid;
      grid-template-columns: repeat(9, 1fr);
      gap: 5px 5px;
      .answer-sheet_chapter-name {
        grid-column: 1 / -1;
        margin-top: 10px;
        font-size: 36rpx;
        color: #303133;
      }
      .answer-sheet__question-no {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 60rpx;
        height: 60rpx;
        border-radius: 50%;
        font-size: 32rpx;
        color: #8f939c;
        border: 1px solid #8f939c;
        background-color: #e9e9eb;
      }
      .answer-sheet__question-no--answer {
        color: #2979ff;
        border: 1px solid #2979ff;
        background-color: #d4e4ff;
      }
      .answer-sheet__question-no--true {
        color: #18bc37;
        border: 1px solid #18bc37;
        background-color: #d1f2d7;
      }
      .answer-sheet__question-no--false {
        color: #e43d33;
        border: 1px solid #e43d33;
        background-color: #fad8d6;
      }
      .answer-sheet__question-no--half {
        color: #18bc37;
        border: 1px solid #18bc37;
        background: linear-gradient(to bottom, #fad8d6 50%, #d1f2d7 50%);
      }
      .answer-sheet__question-no--mark {
        color: #f3a73f;
        background: initial;
        border: 1px solid #f3a73f;
        background-color: #fdedd9;
      }
    }
  }
}
</style>
